﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace config.service
{
    public class Serial : ISerial, IDisposable
    {
        #region 单例实现
        // 使用 Lazy<T> 实现线程安全的单例
        private static readonly Lazy<Serial> _instance = new Lazy<Serial>(() => new Serial());

        // 单例实例访问属性
        public static Serial Instance => _instance.Value;

        // 私有构造函数，防止外部实例化
        private Serial()
        {
            Console.WriteLine("串口单例初始化");
        }
        #endregion

        #region 串口成员变量
        private SerialPort? _serialPort;
        private readonly object _readLock = new object();
        private readonly byte[] _readBuffer = new byte[1024]; // 1KB 固定缓冲区
        private readonly MemoryStream _dataAccumulator = new MemoryStream(8192);
        private bool _disposed = false;
        #endregion

        #region 事件和属性
        public event EventHandler<MemoryStream>? DataReceived;

        public bool IsConnected => _serialPort?.IsOpen ?? false;
        #endregion

        #region 公共方法
        /// <summary>
        /// 断开串口连接
        /// </summary>
        public void Disconnect()
        {
            if (_serialPort?.IsOpen == true)
            {
                _serialPort.DataReceived -= OnDataReceived;
                _serialPort.Close();
            }
            _serialPort?.Dispose();
            _serialPort = null;

            // 重置数据累积器
            _dataAccumulator.SetLength(0);

            Console.WriteLine("串口已断开连接");
        }

        /// <summary>
        /// 获取所有可用的串口名称
        /// </summary>
        public static string[] GetAllSerialPortName()
        {
            return SerialPort.GetPortNames();
        }

        /// <summary>
        /// 连接到串口
        /// </summary>
        public bool Connect(string portName, int baudRate = 9600)
        {
            // 使用锁确保线程安全
            lock (_readLock)
            {
                try
                {
                    // 如果已连接，先断开
                    if (IsConnected)
                    {
                        Console.WriteLine("串口已连接，先断开现有连接");
                        Disconnect();
                    }

                    // 创建串口实例
                    _serialPort = new SerialPort(portName)
                    {
                        BaudRate = baudRate,
                        DataBits = 8,
                        StopBits = StopBits.One,
                        Parity = Parity.None,
                        Handshake = Handshake.None,
                        ReadTimeout = 1000,
                        WriteTimeout = 1000,
                        DtrEnable = true // 必须要打开，否则下位机无法识别串口
                    };

                    // 注册数据接收事件
                    _serialPort.DataReceived += OnDataReceived;

                    // 打开串口
                    _serialPort.Open();

                    Console.WriteLine($"成功连接到串口: {portName}, 波特率: {baudRate}");
                    return true;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"连接串口失败 {portName}: {ex.Message}");
                    Disconnect(); // 确保清理资源
                    return false;
                }
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        public void SendData(byte[] data)
        {
            if (_serialPort == null || !_serialPort.IsOpen)
            {
                throw new InvalidOperationException("串口未连接，无法发送数据");
            }

            lock (_readLock)
            {
                try
                {
                    _serialPort.Write(data, 0, data.Length);
                    Console.WriteLine($"发送数据，长度: {data.Length} 字节");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"发送数据失败: {ex.Message}");
                    throw;
                }
            }
        }

        /// <summary>
        /// 发送字符串数据
        /// </summary>
        public void SendString(string data)
        {
            if (_serialPort == null || !_serialPort.IsOpen)
            {
                throw new InvalidOperationException("串口未连接，无法发送数据");
            }

            lock (_readLock)
            {
                try
                {
                    _serialPort.Write(data);
                    Console.WriteLine($"发送字符串: {data}");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"发送字符串失败: {ex.Message}");
                    throw;
                }
            }
        }

        /// <summary>
        /// 获取当前连接的串口信息
        /// </summary>
        public string GetConnectionInfo()
        {
            if (_serialPort == null || !_serialPort.IsOpen)
            {
                return "串口未连接";
            }

            return $"端口: {_serialPort.PortName}, 波特率: {_serialPort.BaudRate}, 状态: 已连接";
        }
        #endregion

        #region 私有方法
        private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (_serialPort == null || !_serialPort.IsOpen) return;

            // 使用锁防止重入
            lock (_readLock)
            {
                try
                {
                    int totalBytesRead = 0;

                    // 循环读取直到没有数据或缓冲区满
                    while (_serialPort.BytesToRead > 0 && totalBytesRead < _readBuffer.Length)
                    {
                        int bytesToRead = Math.Min(_serialPort.BytesToRead, _readBuffer.Length - totalBytesRead);
                        int bytesRead = _serialPort.Read(_readBuffer, totalBytesRead, bytesToRead);

                        if (bytesRead > 0)
                        {
                            totalBytesRead += bytesRead;
                        }
                        else
                        {
                            break; // 没有读取到数据
                        }
                    }

                    if (totalBytesRead > 0)
                    {
                        // 将数据累积到内存流中
                        _dataAccumulator.Write(_readBuffer, 0, totalBytesRead);

                        // 处理累积的数据
                        DataReceived?.Invoke(this, _dataAccumulator);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"读取数据错误: {ex.Message}");
                    // 重置累积器
                    _dataAccumulator.SetLength(0);
                }
            }
        }
        #endregion

        #region IDisposable 实现
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    Disconnect();
                    _dataAccumulator?.Dispose();
                }
                _disposed = true;
            }
        }

        // 析构函数
        ~Serial()
        {
            Dispose(false);
        }
        #endregion
    }
}